ARD2  RC2
Airbag Reference Demonstrator using MPC5604P
__ppc_eabi_init.c
00001 /***************************************************************************/
00002 /*
00003 
00004 FILE
00005         __ppc_eabi_init.c
00006         $Date: 2010/07/21 13:28:04 $
00007         $Revision: 1.1 $
00008         
00009 DESCRIPTION
00010 
00011         Use this file for C or C++.  Contains calls to initialize memory pools
00012         for use with malloc/free, exceptions and static initializers.  If your
00013         project does not use exceptions, then the initialization code for them 
00014         is stripped out.  If they are used, the linker will add them 
00015         automatically.  A C-only program will be a little smaller (160 bytes) 
00016         with __ppc_eabi_init.c.
00017 
00018         Interface for board-level initialization and user-level initialization.
00019         
00020         If hardware initialization and pre-main user initialization are required,
00021         copy this file to your project directory and customize it (instead of
00022         customizing __start.c).
00023         
00024         Note that __init_hardware should not write on the stack until the
00025         memory controller is properly configured.
00026 
00027         
00028         void __init_hardware(void)
00029         
00030                 Initialize the hardware, including the memory controller.
00031         
00032         void __init_user(void)
00033         
00034                 Allow the user to perform initialization before calling main().
00035         
00036         void __init_cpp(void)
00037         
00038                 CodeWarrior C++ initialization before calling main().  Calls
00039                 constructors of which the cpp exception handling initialization
00040                 is the first constructor, if exceptions are used.
00041         
00042         void __fini_cpp(void)
00043         
00044                 Calls destructors.
00045         
00046         void _ExitProcess(void)
00047                 
00048                 This function simply stalls the debugger.  You may want to rewrite this
00049                 function if you are using an OS.
00050         
00051         abort and exit
00052  
00053         In order to correctly implement the required startup/termination sequence for
00054         C and C++ programs, we need to have an exit() routine that can be called by
00055         the program startup code. The exit() routine is supposed to
00056  
00057                 (1)     call any functions registered via atexit()
00058                 (2) call destructors for any global objects
00059                 (3)     flush any unwritten buffers, close any open files, etc.
00060                 (4) terminates the program
00061  
00062         We don't, however, want to require the ANSI C library for every CodeWarrior
00063         program, since it drags in lots of code that may not be needed.
00064  
00065         Instead we provide a dummy exit() function which simply calls the destructors
00066         and terminates the program. We assume that any program which uses atexit()
00067         or <stdio.h> and which requires those cleanup behaviors will have linked with
00068         the ANSI C library, whose definition of exit() will override the one here.
00069  
00070         We similarly define a dummy abort() function (which is called by the default
00071         terminate() handler).
00072  
00073         Programs which rely on the proper ANSI C/C++ behavior must use the ANSI C
00074         library, and order it in the CodeWarrior project or command-line so that
00075         its definitions supersede these definitions in the runtime support library.
00076 
00077 COPYRIGHT       
00078         (c) 2002-2006 Freescale Semiconductor, Inc.
00079         All rights reserved.
00080 
00081 HISTORY
00082         97 APR 17 LLY   Created.
00083         97 JUN 24 MEA   Added support for C++ and malloc memory heaps.
00084         97 JUN 26 MEA   Made C and C++ versions of this file.  Added abort and exit.
00085         97 JUL 17 SCM   Customized for MPC821 ADS board.
00086         97 JUL 20 MEA   Changed __exit to _ExitProcess so as not to conflict with MSL.
00087                                         _ExitProcess added to this file; removed form __start.c.
00088         99 JAN 22 MEA   Removed exception handing to __init_cpp_exceptions.c for use
00089                                         with 2.2.2 compiler (post Release 4).  Put prototypes for
00090                                         exit and abort within extern "C" to avoid name-mangling.
00091 
00092 */
00093 /***************************************************************************/
00094 
00095 #pragma exceptions off
00096 #pragma ANSI_strict off
00097 #pragma only_std_keywords off
00098 
00099 #define ALLOC_ADDITIONAL_HEAPS 0
00100 #include "MPC5604P.h"
00101 #define FLASH_REG CFLASH.PFCR0.R
00102 #define FLASH_DATA 0x108593FD
00103 /*$FlashRegister2$*/
00104 /*$FlashRegisterValue2$*/
00105 
00106 
00107 #include <__ppc_eabi_init.h>
00108 #include <__ppc_eabi_linker.h>          /* linker-generated symbol declarations */
00109 #if ALLOC_ADDITIONAL_HEAPS
00110 #include <pool_alloc.h>
00111 #endif
00112 
00113 #ifdef __cplusplus
00114 extern "C" {
00115 #endif
00116 
00117 static void __init_cpp(void);
00118 static void __fini_cpp(void);
00119 typedef void (*voidfunctionptr) (void); /* ptr to function returning void */
00120 __declspec(section ".init") extern voidfunctionptr _ctors[];
00121 __declspec(section ".init") extern voidfunctionptr _dtors[];
00122 __declspec(weak) extern void abort(void);
00123 __declspec(weak) extern void exit(int status);
00124 extern void usr_init();
00125 __declspec(section ".init") static int __get_runtime_linktime_delta(void);
00126 __declspec(section ".init") static int __get_linktime_address(void);
00127 __declspec(section ".init") static void __mwerks_fixup_relocations(void);
00128 
00129 #ifdef __cplusplus
00130 }
00131 #endif
00132 
00133 /***************************************************************************/
00134 /*
00135  *      __init_hardware
00136  *
00137  *      Initialize the processor and board.
00138  *
00139  *      Note: this function must not access memory until the memory controller
00140  *      is initialized.  Using "fralloc" (frame allocate) or writing this
00141  *      function in C will cause this routine to break because writing into
00142  *      stack memory is not valid until after usr_init returns.
00143  */
00144 /***************************************************************************/
00145 
00146 asm void __init_hardware(void)
00147 {
00148         /*
00149          *      Initialize board unless running with MWDebug.
00150          *      Uncomment the initialization below if running standalone. 
00151          *      You may need to perform other initializations.
00152          */
00153         nofralloc
00154 
00155    /*
00156         * If we are using Hardware  floating point we need to make sure
00157         * to enable the FP bit in the  MSR
00158         */      
00159 
00160 #if __option(floatingpoint)==1 &&  __option(sfp_emulation)==0
00161         mfmsr r3
00162         ori  r3,r3,0x00002000
00163         mtmsr r3
00164 #endif
00165 
00166    /*
00167         * If we have selected Altivec Programming Model we need to make sure
00168         * to enable the Altivec bit in the  MSR
00169         */      
00170 
00171 #if __VEC__
00172         mfmsr r3
00173         oris r3,r3,0x0200
00174         mtmsr r3
00175 #endif  
00176 
00177    /*
00178         * Enable the MSR[SPE] bit for e500/Zen
00179         */      
00180 
00181 #if defined(__PPCZen__) || defined(__PPCe500__) || defined(__PPCe500v2__)
00182         mfmsr r3
00183         oris   r3,r3,0x0200
00184         mtmsr r3
00185 #endif
00186 
00187         /*
00188          *      When customizing, be aware that the memory controller may not be
00189          *      configured.
00190          */
00191 
00192 #if defined(ROM_VERSION) || defined(CACHE_VERSION) || defined(CALL_USR_INIT)
00193         mflr    r31                                             /* save off return address in NV reg */
00194         bl              usr_init                                /* init board hardware */
00195         mtlr    r31                                             /* get saved return address */
00196 #endif
00197 
00198         blr
00199 }
00200 
00201 #if ALLOC_ADDITIONAL_HEAPS
00202 static void AllocMoreHeaps(void)
00203 {
00204         /*
00205          *      By default, we MSL's allocation (malloc/free) even with C++.
00206          *      If you have declared a heap size in the Project Pref panel,
00207          *      a defaull heap will be created the first time you call
00208          *      malloc.  You can add more calls to init_alloc to create additional
00209          *      heaps.
00210          */
00211         init_alloc(some_address1, some_size1);
00212         init_alloc(some_address2, some_size2);
00213 }
00214 #endif
00215 void FlashConfig(void) 
00216 {
00217                 unsigned int mem_write_code [] = {
00218 
00219                 #if __option(vle)
00220                         /*for processors which support VLE only or for 'VLE on' option*/
00221                 0xD0344400, /* stw r3,(0)r4 machine code: writes r3 contents to addr in r4 then se_nop*/
00222                 0x7C0006AC, /* mbar machine code: ensure prior store completed */
00223                 0x44000004  /* blr machine code: branches to return address in link register */
00224                 #else
00225                         0x90640000, /* stw r3,(0)r4 machine code: writes r3 contents to addr in r4 */
00226                         0x7C0006AC, /* mbar machine code: ensure prior store completed */
00227                         0x4E800020  /* blr machine code: branches to return address in link register */
00228                 #endif // __option(vle)
00229 
00230                         };
00231         
00232 
00233 typedef void (*mem_write_code_ptr_t)(unsigned int, unsigned int);
00234 
00235   #if defined(FLASH_REG) 
00236   (*((mem_write_code_ptr_t)mem_write_code))     /* cast mem_write_code as func ptr*/
00237                                  /* * de-references func ptr, i.e. converts to func*/
00238      (FLASH_DATA,            /* which passes integer (in r3) */
00239       (unsigned int)&FLASH_REG);
00240   #endif      
00241       
00242   #if defined(FLASH_REG2)
00243         (*((mem_write_code_ptr_t)mem_write_code))       /* cast mem_write_code as func ptr*/
00244                                  /* * de-references func ptr, i.e. converts to func*/
00245      (FLASH_DATA2,            /* which passes integer (in r3) */
00246       (unsigned int)&FLASH_REG2);
00247   #endif 
00248  
00249 }
00250 
00251 asm void __init_user(void)
00252 {
00253         fralloc
00254         /*
00255          *      Allocate additional heaps.
00256          */
00257 #if ALLOC_ADDITIONAL_HEAPS
00258         bl              AllocMoreHeaps
00259 #endif
00260 
00261         /*
00262          *      initialization of static initializers
00263          */     
00264 #if (defined(__cplusplus) || defined(__VEC__)) && !defined(DO_NOT_LOAD_CTORS_DTORS)
00265         bl              __init_cpp
00266 #endif
00267         bl FlashConfig
00268         /*
00269          *      Add your initializations here.
00270          */
00271         frfree
00272         blr
00273 }
00274 
00275 #if defined(__cplusplus) || defined(__VEC__)
00276 static void __init_cpp(void)
00277 {
00278         voidfunctionptr *constructor;
00279 
00280         /*
00281          *      call static initializers
00282          */
00283         for (constructor = _ctors; *constructor; constructor++) {
00284                 (*constructor)();
00285         }
00286 }
00287 
00288 static void __fini_cpp(void)
00289 {
00290         voidfunctionptr *destructor;
00291 
00292         /*
00293          *      call destructors
00294          */
00295         for (destructor = _dtors; *destructor; destructor++) {
00296                 (*destructor)();
00297         }
00298 }
00299 #endif
00300 
00301 extern void abort(void)
00302 {
00303         _ExitProcess();
00304 }
00305 
00306 extern void exit(int status)
00307 {
00308         #pragma unused(status)
00309 
00310 #if (defined(__cplusplus) || defined(__VEC__)) && !defined(DO_NOT_LOAD_CTORS_DTORS)
00311         __fini_cpp();
00312 #endif
00313         _ExitProcess();
00314 }
00315 
00316 
00317 /*
00318  *      _ExitProcess
00319  *
00320  *      PowerPC EABI Runtime termination
00321  */
00322 asm void _ExitProcess(void)
00323 {
00324         nofralloc
00325         
00326 #if VLE_ON
00327         /* the inline assembler can not translate this instruction */
00328         se_illegal                                                      /* arbitrary break trap for halt */
00329 #else
00330         opword 0x00454E44                                       /* arbitrary break trap for halt */
00331 #endif
00332 }
00333 
00334 /****************************************************************************/
00335 /*
00336  *      __flush_cache
00337  *
00338  *      For the given memory range, forces all modified data cache contents to be 
00339  *      written to memory and invalidates the associated instruction cache
00340  *      entries.
00341  *      
00342  */
00343 /****************************************************************************/
00344 asm void __flush_cache(register void *address, register unsigned int size)
00345 {
00346 #pragma unused (address, size)
00347         /* r3 is address, r4 is size */
00348         nofralloc
00349 
00350 #if !defined( __PPC555__ ) && !defined( __PPC56X__ )
00351 #if VLE_ON
00352         /* the inline assembler can not translate 2 instructions into 1 */
00353         e_li    r5,0xFFFFFFF1
00354 #else
00355         lis             r5, 0xffff
00356         ori             r5, r5, 0xfff1
00357 #endif
00358         and             r5, r5, r3                              /* make address 8-byte aligned          */
00359         subf    r3, r5, r3                              /* get unaligned-aligned difference     */
00360         add             r4, r4, r3                              /* increase size accordingly            */
00361 
00362 rept:
00363 /*
00364 ** Note: If no data cache, then just invalidate the instruction
00365 ** cache entry.
00366 **
00367 ** The MPC 5xx processors do not have data cache.
00368 */
00369 #if !defined( __PPC505__ ) && !defined( __PPC509__ )
00370 
00371 #if !defined(__PPCGENERIC__)
00372         dcbst   0,r5
00373 #endif
00374 
00375 #endif
00376 
00377 #if defined(__PPCZen__) || defined(__PPCe500__) || defined(__PPCe500v2__)
00378 #if VLE_ON
00379         se_isync
00380 #else
00381         msync
00382 #endif
00383 #else
00384         sync
00385 #endif
00386 
00387         
00388 #if !defined(__PPCGENERIC__)
00389         icbi    0,r5
00390 #endif
00391 
00392         addic   r5,r5,0x8
00393         subic.  r4,r4,0x8
00394         bge             rept
00395         isync
00396 #endif
00397         blr
00398 }
00399 
00400 #if __option(sda_pic_pid)
00401 /* The following functions are used with SDA PIC/PID support.                                           */
00402 /* __init_registers and __init_data will overload weak versions found in __start.c      */
00403 
00404 /***************************************************************************
00405 *** Requirements for SDA PIC/PID ***
00406 
00407 The basic requirement for SDA PIC/PID is that the startup code (.init) and
00408 the segments .sdata and .sdata2 all maintain their link time address 
00409 relationship at runtime.  In other words if the link time addresses are:
00410 .init = 0x00002000
00411 .sdata2 = 0x00003000
00412 .sdata = 0x00004000
00413 but that .init somehow is executed at 0x00002500, then those link time 
00414 addresses must all increment by 0x00000500 for their runtime addresses.  
00415 Any segment that does not maintain the address relationship at runtime is 
00416 considered external and must be addressed with absolute addresses.  
00417 Segments that do maintain their link time address relationship at runtime 
00418 are considered internal and must be addressed with pc and sda relative 
00419 addressing.  More on external and internal segments, below.
00420 
00421 Having .init, .sdata2 and .sdata, as well as other internal segments, end
00422 up at runtime without the link time relationship is not detected in this
00423 runtime but it is at least technically possible for someone to modify the
00424 runtime to support this, at least for a specific application.
00425 
00426 *** Internal and External segments and references ***
00427 
00428 At link time, the linker determines whether code and data segments are 
00429 external or internal.  Internal segments reference their data as far or 
00430 near offsets of the small data registers r2 and r13.  Their code 
00431 references are normally pc relative, but if far code references are 
00432 required, they also use offsets of the small data registers.  Internal
00433 segments can also reference code and data in other internal segments
00434 with the same addressing that they would use for their own code ad data.
00435 By default, all segments in your application are considered internal with 
00436 one exception listed below.
00437 
00438 External segments are segments that are at absolute addresses.  
00439 Segments with a name like .abs.xxxxxxxx, where xxxxxxxx is a hex address
00440 are considered external.  External segments reference their data with 
00441 absolute addressing and code references within the segment can be pc 
00442 relative or absolute.  Any other segment must use absolute references 
00443 to reference code or data in external segments.  External segments must 
00444 reference an internal segment with small data registers for code and data.
00445 
00446 Akin to external segments are external symbol references.  These are 
00447 symbols, usually linker generated symbols, that are determined to be not 
00448 within any segment in your application.  They will be referenced with
00449 absolute addressing.  All symbols in an external segment are considered
00450 to be external symbol references.
00451 
00452 The ldf has 2 mechanisms for you to override the linker's defaults:
00453 1.  The MEMORY directive now supports 
00454 addr_mode = external | internal // default is internal
00455 addr_mode is ignored unless you have chosen the SDA PIC/PID ABI in the EPPC 
00456 Target Pref panel.
00457 
00458 2. New directives INTERNAL_SYMBOL and EXTERNAL_SYMBOL can be used to force
00459 the addressing of global symbols.  These directives are of the 
00460 form XXXL_SYMBOL { sym1, sym2, symN } where the symbols are the link time
00461 symbol names (mangled for c++).
00462 
00463 The auto-generated linker defined start and end symbols for loadable 
00464 segments are internal if they are addresses into internal segments and 
00465 external if they are for external segments.  All other linker defined 
00466 symbols you create in a lcf are considered external unless you redefine
00467 them with INTERNAL_SYMBOL.  The linker also defines some linker defined 
00468 symbols for its own use and they have the following default settings:
00469 
00470 _stack_addr [top of the stack - comes from pref panel settings] external
00471 _stack_end [bottom of the stack - comes from pref panel settings] external
00472 _heap_addr [bottom of the heap - comes from pref panel settings] external
00473 _heap_end [top of the heap - comes from pref panel settings] external
00474 // the next two need to be treated as internal to be EABI compliant so
00475 // you may not redefine them.
00476 _SDA_BASE_ [.sdata + 0x00008000] internal
00477 _SDA2_BASE_ [.sdata2 + 0x00008000] internal
00478 // The previous small data pointers rely on the small data registers being
00479 // properly initialized before being accessible.  However, it is hard to
00480 // initialize those pointers without accessing them as absolutes.
00481 // The following two symbols are external versions of _SDA_BASE_ and
00482 // _SDA2_BASE_ which can be used as absolutes.  You may not redefine them.
00483 _ABS_SDA_BASE_ [.sdata + 0x00008000] external
00484 _ABS_SDA2_BASE_ [.sdata2 + 0x00008000] external
00485 // the following are numbers, not addresses and they must be treated
00486 // as external.  You may not redefine them.
00487 _nbfunctions [number of functions in program - deprecated] external
00488 SIZEOF_HEADERS [size of the segment headers in a linux app] external
00489 
00490 Especially note that the stack and heap linker generated symbols are
00491 external.  It may be more practical in a SDA PIC/PID application to
00492 make the heap and stack be contiguous with an internal segment and
00493 define them as internal.
00494 
00495 *** Uses for SDA PIC/PID ***
00496 
00497 The runtime was developed for 3 different situations:
00498 
00499 1. All code and data segments are internal.  The simplest case would be
00500 for all segments to use the same MEMORY directive and to have all of the 
00501 bss type segments at the end.  In such a simple case, the application could
00502 be converted to a binary file and linked into another application which
00503 could copy it to ram and jump to its entry point.
00504 
00505 2. All of the essential segments are internal and therefore moveable but 
00506 there may be some external segments which are absolute.  This situation is 
00507 probably difficult to test but you can download the entire application
00508 to the chip and at least debug it at its link time addresses.
00509 
00510 3. Like 2, there are internal and external segments but the application is 
00511 linked as a ROM image - the application does not need to be flashed to
00512 ROM, however.  It is possible to change the ROM Image Address to be an
00513 address into RAM and have the debugger download the image to the RAM 
00514 address.  Alternatively, you could have the ROM image converted to a bin
00515 file and link it into another application as in 1, above.  The structures 
00516 used in __init_data(), _rom_copy_info and __bss_init_info, have been 
00517 modified for SDA PIC/PID to have an extra field which tells the runtime 
00518 where the segment is internal or external so that the internal segments 
00519 will be copied to position relative addresses and the external segments 
00520 will be copied to absolute addresses.
00521 
00522 *** Compiler/Linker support for SDA Addressing ***
00523 You build a SDA PIC/PID application by selecting SDA PIC/PID in the ABI
00524 popup in the EPPC Target Preference panel.  When you chose that, the 
00525 compiler will define a simple that you can use to guard PIC/PID source.
00526 
00527 #if __option(sda_pic_pid) // is true if you have chosen SDA PIC/PID ABI
00528 
00529 If you then link, the linker will generate a table for the runtime files
00530 __ppc_eabi_init.cpp/__ppc_eabi_init.c to use.  If your application has
00531 absolute addressing relocations (which it would by default) you will
00532 probably get linker warnings telling you that those relocations may
00533 cause a problem.  If that happens, you have two choices.  You can change
00534 the Code Model popup in the EPPC Target Preference panel to be
00535 SDA Based PIC/PID Addressing for all of your sources and libraries, and/or
00536 check the Tune Relocations checkbox in the EPPC Target Preference panel.
00537 This new option is only available for the EABI and SDA PIC/PID ABIs.  For
00538 EABI it changes 14 bit branch relocations to 24 bit branch relocations
00539 only if they can not reach the calling site from the original relocation.
00540 For SDA PIC/PID, it changes absolute addressed references of data from
00541 code to use a small data register instead of r0 and changes absolute
00542 code to code refernces to use the pc relative relocations.  In general,
00543 this will work well for normnal compiled code.  It is always possible
00544 to link in an assembly file that does not behave in a standard way.
00545 
00546 Whether you use the Code Model SDA Based PIC/PID Addressing or not,
00547 #pragma section has been modified to accept far_sda_rel for the data_mode
00548 and code_mode options.  If you leave those options out, the compiler
00549 will you the Code Model to determine the appropriate modes.
00550 
00551 Absolute Addressing defaults to data_mode = far_abs and code_mode = pc_rel.
00552 SDA Based PIC/PID Addressing defaults to data_mode = far_sda_rel and
00553 code_mode = pc_rel.
00554 
00555 ***************************************************************************/
00556 
00557 /***************************************************************************/
00558 /*
00559  *      __get_runtime_linktime_delta
00560  *
00561  *      Assumes that r13 and r2 are initialized correctly and that they always
00562  *      stay in the same relationship to each other.
00563  *
00564  *      Utility function to get difference between runtime and linktime addresses.
00565  *
00566  */
00567 /***************************************************************************/
00568 static asm int __get_runtime_linktime_delta(void)
00569 {
00570         nofralloc
00571     /* _ABS_SDA_BASE_, generated by the linker, is the same value as                    */
00572         /* _SDA_BASE_ but forces the linker to treat it as absolutetly addressed        */
00573         /* and not to substitute r13 for r0.  We therefore end up with r3 exactly       */
00574         /* as calculated at linktime.                                                                                           */
00575         addis   r3, r0, _ABS_SDA_BASE_@ha
00576         addi    r3, r3, _ABS_SDA_BASE_@l
00577         /* Subtract the runtime from the linktime address.                                                      */
00578         sub             r3,r13,r3
00579         blr
00580 }
00581 
00582 /***************************************************************************/
00583 /*
00584  *      __mwerks_fixup_relocations
00585  *
00586  *      Modify initialized pointers in the data sections to reflect correct
00587  *      runtime addresses.  The linker created a table, _f_mwerks_fixup, of 
00588  *      offsets into the data sections that need modification.  This function
00589  *      loads the pointer at that offset and applies the runtime/linktime
00590  *      delta.  We wait to call this function until after __init_data.
00591  *
00592  */
00593 /***************************************************************************/
00594 static asm void __mwerks_fixup_relocations(void)
00595 {
00596         nofralloc
00597         
00598         /* r13, r2, and r1 have their correct runtime values.                                           */
00599 
00600     mflr    r0
00601 
00602         /* If runtime and linktime addresses are the same, no fixup is necessary.       */
00603         bl              __get_runtime_linktime_delta
00604     cmpli   cr0,r3,0
00605     beq     no_fixup
00606 
00607         /* Initialize runtime addresses of the fixup table.  _f_mwerks_fixup is the     */
00608         /* beginning of the table and _e_mwerks_fixup is the end.  Note that r0         */
00609         /* will get converted to r13 or r2 by the linker.                                                       */
00610     addis   r5,r0,_f_mwerks_fixup@ha
00611     addis   r4,r0,_e_mwerks_fixup@ha
00612     addi    r5,r5,_f_mwerks_fixup@l
00613     addi    r4,r4,_e_mwerks_fixup@l
00614 
00615     /* Compute number of entries ((_e_mwerks_fixup - _f_mwerks_fixup) / 4).             */
00616     subf    r6,r5,r4                    
00617     /* If there are no entries, bail.                                                                                   */
00618     cmpli   cr0,r6,0
00619     beq     no_fixup
00620     srwi    r6,r6,2
00621     mtctr   r6
00622         /* We use pre-increment, so move to first real entry - 4.                                       */
00623     subi    r5,r5,4
00624 fixup_loop:
00625         /* Load address of relocation.                                                                                          */
00626     lwzu    r6,4(r5)
00627     /* Update address using SDA delta.                                                                                  */
00628     add     r6,r6,r3
00629     /* Load value at relocation.                                                                                                */
00630     lwz     r7,0(r6)
00631     /* Update value using SDA delta.                                                                                    */
00632     add     r7,r7,r3
00633     /* Store updated value.                                                                                                             */
00634     stw     r7,0(r6)
00635     bdnz    fixup_loop
00636 no_fixup:
00637     mtlr    r0
00638     blr
00639 }
00640 
00641 /***************************************************************************/
00642 /*
00643  *      __init_registers
00644  *
00645  *      Initialize PowerPC EABI Registers
00646  *
00647  *      Note: this function is guaranteed to not reference any memory; the memory
00648  *      controller may not be initialized.
00649  *
00650  *      we now overload the function in the event that the user wants pic pid
00651  *
00652  */
00653 /***************************************************************************/
00654 asm extern void __init_registers(void)
00655 {
00656         nofralloc                                               /* see above on usage of nofralloc */
00657 
00658     mflr    r0
00659 
00660         /* _ABS_SDA_BASE_, generated by the linker, is the same value as                        */
00661         /* _SDA_BASE_ but forces the linker to treat it as absolutetly addressed        */
00662         /* and not to substitute r13 for r0.  We therefore end up with r13 exactly      */
00663         /* as calculated at linktime.                                                                                           */
00664         addis   r13, r0, _ABS_SDA_BASE_@ha
00665         addi    r13, r13, _ABS_SDA_BASE_@l
00666 
00667         /* _ABS_SDA2_BASE_, generated by the linker, is the same value as                       */
00668         /* _SDA2_BASE_ but forces the linker to treat it as absolutetly addressed       */
00669         /* and not to substitute r2 for r0.  We therefore end up with r2 exactly        */
00670         /* as calculated at linktime.                                                                                           */
00671         addis   r2, r0, _ABS_SDA2_BASE_@ha
00672         addi    r2, r2, _ABS_SDA2_BASE_@l
00673    
00674         /* Grab the runtime address of __get_linktime_address.  The bcl will put        */
00675         /* __get_linktime_address into LR. */
00676         bcl     20,31,__get_linktime_address
00677 entry __get_linktime_address
00678         /* Move runtime address of __get_linktime_address from LR to r4. */
00679         mflr    r4
00680 
00681         /* Grab the linktime address of __get_linktime_address.  Note that r0 will      */
00682         /* get converted to r13 or r2 by the linker but because r13 and r2 may not      */
00683         /* reflect the their runtime values yet, r3 might not equal r4.                         */
00684     addis   r3,r0,__get_linktime_address@ha
00685     addi    r3,r3,__get_linktime_address@l
00686     
00687         /* Subtract the runtime from the linktime address.                                                      */
00688         sub             r3,r4,r3
00689         /* If runtime and linktime addresses are the same, no fixup is necessary.       */
00690     cmpli   cr0,r3,0
00691     beq     no_fixup
00692 
00693         /* Add the delta into small data pointers so they will reflect the current      */
00694         /* position of code and data.                                                                                           */
00695         add             r13,r13,r3
00696         add             r2,r2,r3
00697 no_fixup:
00698 
00699         /* Initialize runtime address of _stack_addr.  Note that r0 will                        */
00700         /* get converted to r13 or r2 by the linker if _stack_addr is                           */
00701         /* treated as an internal symbol (default is external).                                         */
00702         addis   r1, r0, _stack_addr@ha
00703         addi    r1, r1, _stack_addr@l
00704     mtlr    r0
00705 
00706         blr
00707 }
00708 
00709 /***************************************************************************/
00710 /*
00711  *      __init_data
00712  *
00713  *      Initialize all (RAM) data sections, copying ROM sections as necessary.
00714  *
00715  *      dst                     destination RAM address
00716  *      size            number of bytes to zero
00717  *
00718  *      we now overload the function in the event that the user wants pic pid
00719  *
00720  */
00721 /***************************************************************************/
00722 extern void __init_data(void)
00723 {
00724         __pic_rom_copy_info *dci;
00725         __pic_bss_init_info *bii;
00726         int                                     delta = __get_runtime_linktime_delta();
00727         unsigned int            size;
00728         unsigned char           *ram_addr;              /* address in ram (executing address) */
00729         unsigned char           *ram_end;               /* end address in ram (executing address) */
00730         unsigned char           *rom_addr;              /* address in rom */
00731         unsigned char           *rom_end;               /* end address in rom */
00732         int                                     internal;
00733                 
00734         /* for sda pic pid, if ram_end and ram_addr are swapped so that ram_end < ram_addr,             */
00735         /* then segment is internal, otherwise it is external.  for eabi, addresses are external        */
00736 
00737         dci = _pic_rom_copy_info;
00738         while (1) {
00739                 if (dci->rom_addr == 0 && dci->ram_addr == 0 && dci->ram_end == 0) break;
00740                 internal = (dci->rom_end < dci->rom_addr);
00741                 if (internal) {
00742                         rom_addr = dci->rom_end + delta;
00743                         rom_end = dci->rom_addr + delta;
00744                 } else {
00745                         rom_addr = dci->rom_addr;
00746                         rom_end = dci->rom_end;
00747                 }
00748                 internal = (dci->ram_end < dci->ram_addr);
00749                 if (internal) {
00750                         ram_addr = dci->ram_end + delta;
00751                         ram_end = dci->ram_addr + delta;
00752                 } else {
00753                         ram_addr = dci->ram_addr;
00754                         ram_end = dci->ram_end;
00755                 }
00756                 size = (unsigned int) (ram_end - ram_addr);
00757                 __copy_rom_section(ram_addr, rom_addr, size);
00758                 dci++;
00759         }
00760  
00761         /* Initialize with zeros: */
00762 
00763         bii = _pic_bss_init_info;
00764         while (1) {
00765                 if (bii->ram_addr == 0 && bii->ram_end == 0) break;
00766                 internal = (bii->ram_end < bii->ram_addr);
00767                 if (internal) {
00768                         ram_addr = bii->ram_end + delta;
00769                         ram_end = bii->ram_addr + delta;
00770                 } else {
00771                         ram_addr = bii->ram_addr;
00772                         ram_end = bii->ram_end;
00773                 }
00774                 size = (unsigned int) (ram_end - ram_addr);
00775                 __init_bss_section(ram_addr, size);
00776                 bii++;
00777         }
00778         
00779         /* now that data is copied to ram, we can fix up initialized pointers */
00780         __mwerks_fixup_relocations();   
00781 }
00782 
00783 /***************************************************************************/
00784 /*
00785  *      __exception_info_constants
00786  *
00787  *      Called from __init_cpp_exceptions.cpp
00788  *
00789  *      info            address of linker generated exception table info
00790  *      R2                      address of variable to hold the value in r2
00791  *
00792  *      we now overload the function in the event that the user wants pic pid
00793  *
00794  */
00795 /***************************************************************************/
00796 extern void __exception_info_constants(void **info, char **R2)
00797 {
00798         register char *temp;                            /* r2 register contents                                                         */
00799 
00800         asm {
00801                 mr      temp,r2
00802         }
00803         *R2 = temp;
00804         
00805         *info = _pic_eti_init_info;
00806 }
00807 
00808 /***************************************************************************/
00809 /*
00810  *      __find_exception_addresses
00811  *
00812  *      Called from ExceptionPPC.cp
00813  *
00814  *      info            address of linker generated exception table info
00815  *      returnaddr      address within a code segment
00816  *      returnaddr      address within a code segment
00817  *      ex_start        address of variable to hold address of exception table info
00818  *      ex_end          address of variable to hold end address of exception table info
00819  *
00820  *      we now overload the function in the event that the user wants pic pid
00821  *
00822  */
00823 /***************************************************************************/
00824 extern int __find_exception_addresses(void *info, char *returnaddr, void **ex_start, void **ex_end)
00825 {
00826         __pic_eti_init_info     *eti_info = (__pic_eti_init_info*)info;
00827         unsigned char           *start;                 /* address */
00828         unsigned char           *end;                   /* end address */
00829         int                                     internal;
00830         int                                     delta = __get_runtime_linktime_delta();
00831         
00832         while (1) {
00833                 if (eti_info->code_end - eti_info->code_start == 0) break;
00834                 internal = (eti_info->code_end < eti_info->code_start);
00835                 if (internal) {
00836                         start = eti_info->code_end + delta;
00837                         end = eti_info->code_start + delta;
00838                 } else {
00839                         start = eti_info->code_start;
00840                         end = eti_info->code_end;
00841                 }
00842                 if((unsigned char*)returnaddr>=start && (unsigned char*)returnaddr<end) {
00843                         internal = (eti_info->eti_end < eti_info->eti_start);
00844                         if (internal) {
00845                                 start = eti_info->eti_end + delta;
00846                                 end = eti_info->eti_start + delta;
00847                         } else {
00848                                 start = eti_info->eti_start;
00849                                 end = eti_info->eti_end;
00850                         }
00851                         *ex_start = start;
00852                         *ex_end = end;
00853                         return(1);
00854                 }
00855                 eti_info++;
00856         }
00857         
00858         return(0);
00859 }
00860 
00861 
00862 #endif